import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import LabelEncoder

# 设置matplotlib使用宋体作为默认字体
plt.rcParams['font.sans-serif'] = ['SimSun']
plt.rcParams['font.size'] = 12

file_path = 'D:/pycharm/data/ml-latest-small/tags.csv'
data = pd.read_csv(file_path)

data['rating'] = data.groupby('userId')['timestamp'].transform(lambda x: x.rank())

# 提取特征和目标变量，并确保y为一维数组形式
X = data['tag'].values.reshape(-1, 1)
y = data['rating'].values.ravel()

# 对特征变量X中的字符串标签进行标签编码
label_encoder = LabelEncoder()
X_encoded = label_encoder.fit_transform(X)

# 确保X_encoded为二维数组形式，如果不是则进行调整
if X_encoded.ndim == 1:
    X_encoded = X_encoded.reshape(-1, 1)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_encoded, y, test_size=0.2, random_state=42)

# 创建并训练线性回归模型
model = LinearRegression()
model.fit(X_train, y_train)

# 在训练集上进行预测
y_train_pred = model.predict(X_train)

# 计算训练集指标
mse_train = mean_squared_error(y_train, y_train_pred)
r2_train = r2_score(y_train, y_train_pred)

print("训练集均方误差（MSE）:", mse_train)
print("训练集决定系数（R²）:", r2_train)

# 在测试集上进行预测
y_test_pred = model.predict(X_test)

# 计算测试集指标
mse_test = mean_squared_error(y_test, y_test_pred)
r2_test = r2_score(y_test, y_test_pred)

print("测试集均方误差（MSE）:", mse_test)
print("测试集决定系数（R²）:", r2_test)

# 不同参数设置下的指标存储列表
mse_train_list = []
r2_train_list = []
mse_test_list = []
r2_test_list = []

# 尝试不同的fit_intercept参数值
for fit_intercept_value in [True, False]:
    model = LinearRegression(fit_intercept=fit_intercept_value)
    model.fit(X_train, y_train)

    # 在训练集上进行预测并计算指标
    y_train_pred = model.predict(X_train)
    mse_train = mean_squared_error(y_train, y_train_pred)
    r2_train = r2_score(y_train, y_train_pred)
    mse_train_list.append(mse_train)
    r2_train_list.append(r2_train)

    # 在测试集上进行预测并计算指标
    y_test_pred = model.predict(X_test)
    mse_test = mean_squared_error(y_test, y_test_pred)
    r2_test = r2_score(y_test, y_test_pred)
    mse_test_list.append(mse_test)
    r2_test_list.append(r2_test)

# 绘制训练集指标图表
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot([True, False], mse_train_list, marker='o')
plt.xlabel('fit_intercept')
plt.ylabel('均方误差（MSE）')
plt.title('训练集均方误差随参数变化')

plt.subplot(1, 2, 2)
plt.plot([True, False], r2_train_list, marker='o')
plt.xlabel('fit_intercept')
plt.ylabel('决定系数（R²）')
plt.title('训练集决定系数随参数变化')
plt.show()

# 绘制测试集指标图表
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot([True, False], mse_test_list, marker='o')
plt.xlabel('fit_intercept')
plt.ylabel('均方误差（MSE）')
plt.title('测试集均方误差随参数变化')

plt.subplot(1, 2, 2)
plt.plot([True, False], r2_test_list, marker='o')
plt.xlabel('fit_intercept')
plt.ylabel('决定系数（R²）')
plt.title('测试集决定系数随参数变化')
plt.show()

# 分析比较测试集指标结果
if mse_test_list[0] < mse_test_list[1]:
    print("当fit_intercept为", [True, False][0], "时，测试集均方误差更小，模型性能可能更好。")
else:
    print("当fit_intercept为", [True, False][1], "时，测试集均方误差更小，模型性能可能更好。")

if r2_test_list[0] > r2_test_list[1]:
    print("当fit_intercept为", [True, False][0], "时，测试集决定系数更大，模型拟合效果可能更好。")
else:
    print("当fit_intercept为", [True, False][1], "时，测试集决定系数更大， model fitting effect may be better.")

print("模型训练与评估报告")
print("----------------------")
print("数据集基本信息：")
print("数据集中包含", len(data), "条记录。")
print("特征变量为电影标签（tag），目标变量为假设的用户对电影的评分（rating）。")
print("----------------------")
print("初始模型训练结果：")
print("训练集均方误差（MSE）:", mse_train)
print("训练集决定系数（R²）:", r2_train)
print("测试集均方误差（MSE）:", mse_test)
print("测试集决定系数（R²）:", r2_test)
print("----------------------")
print("模型调参结果：")
print("通过改变fit_intercept参数进行调参，不同参数下的测试集指标分析如下：")
if mse_test_list[0] < mse_test_list[1]:
    print("当fit_intercept为", [True, False][0], "时，测试集均方误差更小，模型性能可能更好。")
else:
    print("当fit_intercept为", [True, False][1], "时，测试集均方误差更小， model fitting effect may be better.")

if r2_test_list[0] > r2_test_list[1]:
    print("当fit_intercept为", [True, False][0], "时，测试集决定系数更大， model fitting effect may be better.")
else:
    print("当fit_intercept为", [True, False][1], "时，测试集决定系数更大， model fitting effect may be better.")